namespace YM {
    export class EntityFactory {
        public static createWithParent<T extends Entity>(type: { new(): T }, parent: Entity): T;
        public static createWithParent<T extends Entity, A>(type: { new(): T }, parent: Entity, a: A): T;
        public static createWithParent<T extends Entity, A, B>(type: { new(): T }, parent: Entity, a: A, b: B): T;
        public static createWithParent<T extends Entity, A, B, C>(type: { new(): T }, parent: Entity, a: A, b: B, c: C): T;
        public static createWithParent<T extends Entity, A, B, C>(type: { new(): T }, parent: Entity, a?: A, b?: B, c?: C): T {
            let component = game.objectPool.fetch(type);
            component.domain = parent.domain;
            component.id = component.instanceId;
            component.parent = parent;
            if (!a && !b && !c) {
                game.event.awake(component);
            }
            else if (a && !b && !c) {
                game.event.awake(component, a);
            }
            else if (a && b && !c) {
                game.event.awake(component, a, b);
            }
            else if (a && b && c) {
                game.event.awake(component, a, b, c);
            }
            return component;
        }
        public static create<T extends Entity>(type: { new(): T },domain:Entity): T
        public static create<T extends Entity,A>(type: { new(): T },domain:Entity,a:A): T
        public static create<T extends Entity,A,B>(type: { new(): T },domain:Entity,a:A,b:B): T
        public static create<T extends Entity,A,B,C>(type: { new(): T },domain:Entity,a:A,b:B,c:C): T
        public static create<T extends Entity,A,B,C>(type: { new(): T },domain:Entity,a?:A,b?:B,c?:C):T
		{			
            let component = game.objectPool.fetch(type);
            if(domain!=null){
                component.domain =domain;
            }
            else{
                component.domain=component;
            }
			component.id = component.instanceId;
            if (!a && !b && !c) {
                game.event.awake(component);
            }
            else if (a && !b && !c) {
                game.event.awake(component, a);
            }
            else if (a && b && !c) {
                game.event.awake(component, a, b);
            }
            else if (a && b && c) {
                game.event.awake(component, a, b, c);
            }
			return component;
		}
        public static createWithId<T extends Entity>(type: { new(): T },domain:Entity,id:number): T
        public static createWithId<T extends Entity,A>(type: { new(): T },domain:Entity,id:number,a:A): T
        public static createWithId<T extends Entity,A,B>(type: { new(): T },domain:Entity,id:number,a:A,b:B): T
        public static createWithId<T extends Entity,A,B,C>(type: { new(): T },domain:Entity,id:number,a:A,b:B,c:C): T
        public static createWithId<T extends Entity,A,B,C>(type: { new(): T },domain:Entity,id:number,a?:A,b?:B,c?:C):T
		{			
            let component = game.objectPool.fetch(type);
            if(domain!=null){
                component.domain =domain;
            }
            else{
                component.domain=component;
            }
			component.id = id;
            if (!a && !b && !c) {
                game.event.awake(component);
            }
            else if (a && !b && !c) {
                game.event.awake(component, a);
            }
            else if (a && b && !c) {
                game.event.awake(component, a, b);
            }
            else if (a && b && c) {
                game.event.awake(component, a, b, c);
            }
			return component;
        }
        public static createScene(sceneType:SceneType = SceneType.Client, name:string = "Client", parent:Scene = null, id:number = 0):Scene
		{
			let scene = game.objectPool.fetch(Scene);

			scene.id = id != 0 ? id : IdGenerater.GenerateInstanceId();
			scene.name = name;
			scene.sceneType = sceneType;

			if (parent != null)
			{
				scene.parent = parent;
			}

			scene.domain = scene;

			return scene;
		}
    }
}